package com.mfp.java.testYou.core.servlets;

import java.sql.SQLException;
import java.util.LinkedList;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import com.mfp.java.testYou.core.AppContext;
import com.mfp.java.testYou.core.Constants;
import com.mfp.java.testYou.core.utils.UrlUtils;
import com.mfp.java.testYou.db.model.Answer;
import com.mfp.java.testYou.db.model.Question;
import com.mfp.java.testYou.ui.mvc.QuestionPage;
import com.mfp.java.testYou.ui.mvc.QuestionsPage;

public class ManageQuestionServlet extends HttpServlet {

	private static final long serialVersionUID = 5879869743438692645L;
	private static final Logger log = Logger.getLogger(ManageQuestionServlet.class);

	// same value as in web.xml
	public static final String URL = "/testYou/manageQuestion.html";

	public static final String OPERATION = "operation";

	public static final String OPERATION_NEW = "new";
	public static final String OPERATION_EDIT = "edit";
	public static final String OPERATION_DELETE = "delete";
	public static final String OPERATION_ADD = "add";
	public static final String OPERATION_CHANGE = "change";

	public static final String INPUT_Q_TEXT = "qText";
	public static final String INPUT_HINT = "hint";
	public static final String INPUT_ANSW_TEXT = "answ";
	public static final String INPUT_ANSW_CORR = "corr";

	public static final String INPUT_QUESTIONID = "questionId";

	public void doGet(HttpServletRequest req, HttpServletResponse resp) {
		doPost(req, resp);
	}

	public void doPost(HttpServletRequest req, HttpServletResponse resp) {
		if (OPERATION_NEW.equals(getOperation(req))) {
			UrlUtils.forwardToTarget(req, resp, QuestionPage.URL);
			return;
		}

		if (OPERATION_EDIT.equals(getOperation(req))) {
			loadQuestion(req, QuestionPage.ATTR_EDIT_QUESTION);
			UrlUtils.forwardToTarget(req, resp, QuestionPage.URL);
			return;
		}

		if (OPERATION_ADD.equals(getOperation(req))) {
			createQuestion(req);
			UrlUtils.forwardToTarget(req, resp, QuestionPage.URL);
			return;
		}

		if (OPERATION_DELETE.equals(getOperation(req))) {
			deleteQuestion(req);
			UrlUtils.redirectToTarget(req, resp, QuestionsPage.URL);
			return;
		}

		if (OPERATION_CHANGE.equals(getOperation(req))) {
			editQuestion(req);
			UrlUtils.redirectToTarget(req, resp, QuestionsPage.URL);
			return;
		}

		log.error("Unknown command: " + getOperation(req));
		UrlUtils.redirectToTarget(req, resp, QuestionsPage.URL);
	}

	private void editQuestion(HttpServletRequest req) {

		Question question = buildQuestionFromRequest(req);

		try {
			String qId = req.getParameter(INPUT_QUESTIONID);
			Integer qIdInt = new Integer(qId);

			AppContext.getDAO().editQuestion(question, qIdInt);
			AppContext.getUserSession(req).setMessage(Constants.I18N_QUESTION_EDITED);
			log.info("Edited user: " + question.toString());

		} catch (IllegalArgumentException e) {
			log.error(e.getClass().getName() + " " + e.getMessage());
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
		} catch (SQLException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_DB_ERROR);
			log.error(e.getClass().getName() + " " + e.getMessage());
		}
	}

	private String getOperation(HttpServletRequest request) {
		return request.getParameter(OPERATION);
	}

	private void loadQuestion(HttpServletRequest req, String attrName) {
		try {
			String qId = req.getParameter(INPUT_QUESTIONID);
			Integer qIdInt = new Integer(qId);
			Question q = AppContext.getDAO().getQuestion(qIdInt);
			req.setAttribute(attrName, q);
		} catch (IllegalArgumentException e) {
			log.error("Error while loading question: " + e.getClass().getName() + " " + e.getMessage());
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
		}
	}

	private void createQuestion(HttpServletRequest req) {
		try {
			Question q = buildQuestionFromRequest(req);

			AppContext.getDAO().addQuestion(q);
			log.info("Created question: " + q.toString());
			AppContext.getUserSession(req).setMessage(Constants.I18N_QUESTION_CREATED);


		} catch (IllegalArgumentException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
			log.error(e.getClass().getName() + " " + e.getMessage());
		} catch (SQLException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_DB_ERROR);
			log.error(e.getClass().getName() + " " + e.getMessage());
		}
	}

	private Question buildQuestionFromRequest(HttpServletRequest req) throws IllegalArgumentException {
		try {
			Question q = new Question();

			String questionText = req.getParameter(INPUT_Q_TEXT);
			String hint = req.getParameter(INPUT_HINT);

			q.setText(questionText);
			q.setHint(hint);
			q.setAnswers(new LinkedList<Answer>());

			int i = 1;
			while (true) {
				String answ = req.getParameter(INPUT_ANSW_TEXT + i);
				String corr = req.getParameter(INPUT_ANSW_CORR + i);

				if (answ == null || answ.length() == 0) {
					break;
				}

				q.getAnswers().add(new Answer("on".equalsIgnoreCase(corr), answ));

				i++;
			}

			return q;
		} catch (NullPointerException npe) {
			log.warn(npe.getClass().getName() + " " + npe.getMessage());
			throw new IllegalArgumentException(npe);
		}
	}

	private void deleteQuestion(HttpServletRequest req) {
		String questId = req.getParameter(INPUT_QUESTIONID);
		try {
			Integer userIdInt = new Integer(questId);
			AppContext.getDAO().deleteQuestion(userIdInt);
			AppContext.getUserSession(req).setMessage(Constants.I18N_QUESTION_DELETED);
			log.info("Deleted question with id: " + questId);
		} catch (SQLException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_DB_ERROR);
			log.error(e.getClass().getName() + " " + e.getMessage());
		} catch (IllegalArgumentException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
			log.error(e.getClass().getName() + " " + e.getMessage());
		}
	}
}
